package com.example.springpethospital.controller;

import com.example.springpethospital.entity.*;
import com.example.springpethospital.service.*;
import com.example.springpethospital.util.Utility;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.*;
import java.io.*;
import java.net.URLEncoder;

@Controller
@RequestMapping("/illManage")
@CrossOrigin(originPatterns = "*", allowCredentials = "true", allowedHeaders = "*")
public class IllcaseFileController {
    @Autowired
    IllcaseFileService illcaseFileService;
    @Autowired
    UserService userService;

    private static final int DEFAULT_BUFFER_SIZE = 16384;

    @GetMapping("/getFileList")
    @ResponseBody
    public Object getFileList(HttpServletRequest request) {
        try {
            int caseID = Integer.parseInt(request.getParameter("caseID"));
            int casetype = Integer.parseInt(request.getParameter("casetype"));
            int filetype = Integer.parseInt(request.getParameter("filetype"));
            return Utility.newResponseObject(true,
                    illcaseFileService.getFileList(caseID, CaseType.toCaseType(casetype), FileType.toFileType(filetype)));
        } catch (IllegalArgumentException ex) {
            return Utility.newResponseObject("请求参数格式不正确，caseID应为正整数，casetype应为0~3，filetype应为0~2");
        }
    }

    @GetMapping("/getFile")
    public void getFile(HttpServletRequest request, HttpServletResponse response) {
        InputStream inputStream = null;
        RandomAccessFile inputFile = null;
        OutputStream outputStream = null;
        try {
            int id = Integer.parseInt(request.getParameter("id"));
            FileAndFiletype fileAndType = illcaseFileService.getFile(id);
            if (fileAndType == null || fileAndType.file == null || !fileAndType.file.exists()) {
                response.sendError(404);
                return;
            }
            switch (fileAndType.fileType) {
                case Image:
                    response.setContentType("image/jpeg");
                    response.setHeader("Content-Disposition", "inline");
                    break;
                case Video:
                    response.setContentType("video/mp4");
                    response.setHeader("Content-Disposition", "inline");
                    break;
                case Other:
                    response.setContentType("multipart/form-data");
                    response.setHeader("Content-Disposition",
                            "attachment; fileName=" + URLEncoder.encode(fileAndType.file.getName(), "UTF-8"));
                    break;
            }
            response.setHeader("Last-Modified", String.valueOf(fileAndType.file.lastModified()));
            outputStream = response.getOutputStream();
            if (fileAndType.fileType == FileType.Image) {
                inputStream = new FileInputStream(fileAndType.file);
                IOUtils.copy(inputStream, outputStream);
            } else {
                // 视频和文件支持断点传输
                long fileSize = fileAndType.file.length();
                long start = 0, end = fileSize;
                String range = request.getHeader(HttpHeaders.RANGE);
                if (range != null) {
                    String[] rangeArr = range.replaceAll("bytes=", "").split("-");
                    start = Long.parseLong(rangeArr[0]);
                    if (rangeArr.length > 1) end = Long.parseLong(rangeArr[1]) + 1;
                    response.setStatus(HttpStatus.PARTIAL_CONTENT.value());
                }
                response.setHeader("Accept-Ranges", "bytes");
                response.setHeader("Content-Range", String.format("bytes %d-%d/%d", start, end - 1, fileSize));
                response.setHeader("Content-Length", String.valueOf(end - start));
                inputFile = new RandomAccessFile(fileAndType.file, "r");
                inputFile.seek(start);
                byte[] buff = new byte[DEFAULT_BUFFER_SIZE];
                int clen;
                while (inputFile.getFilePointer() < end && (clen = inputFile.read(buff)) > 0) {
                    outputStream.write(buff, 0, clen);
                }
            }
        } catch (NumberFormatException | FileNotFoundException ex) {
            try {
                response.sendError(404);
            } catch (IOException ignored) {
            }
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        } finally {
            try {
                if (inputStream != null) inputStream.close();
                if (inputFile != null) inputFile.close();
                if (outputStream != null) outputStream.close();
            } catch (IOException ignored) {
            }
        }
    }

    @AdminMethod
    @PostMapping("/AddFile")
    @ResponseBody
    public Object AddFile(HttpServletRequest request, @RequestParam("file") MultipartFile file) {
        try {
            int caseID = Integer.parseInt(request.getParameter("caseID"));
            CaseType casetype = CaseType.toCaseType(Integer.parseInt(request.getParameter("casetype")));
            FileType filetype = FileType.toFileType(Integer.parseInt(request.getParameter("filetype")));
            illcaseFileService.AddFile(caseID, casetype, filetype, file);
            return Utility.newResponseObject(true);
        } catch (IOException | IllegalArgumentException ex) {
            return Utility.newResponseObject(ex.getMessage());
        }
    }

    @AdminMethod
    @PostMapping("/DeleteFile")
    @ResponseBody
    public Object DeleteFile(HttpServletRequest request) {
        try {
            int fileID = Integer.parseInt(request.getParameter("id"));
            if (illcaseFileService.DeleteFile(fileID))
                return Utility.newResponseObject(true);
            else
                return Utility.newResponseObject("删除失败，可能文件已删除");
        } catch (NumberFormatException ex) {
            return Utility.newResponseObject("请求格式不正确");
        }
    }

    @AdminMethod
    @PostMapping("/modifyFileProperties")
    @ResponseBody
    public Object modifyFileProperties(HttpServletRequest request) {
        try {
            int fileID = Integer.parseInt(request.getParameter("id"));
            int caseID = Integer.parseInt(request.getParameter("caseID"));
            CaseType casetype = CaseType.toCaseType(Integer.parseInt(request.getParameter("casetype")));
            FileType filetype = FileType.toFileType(Integer.parseInt(request.getParameter("filetype")));
            illcaseFileService.modifyFileProperties(fileID, caseID, casetype, filetype);
            return Utility.newResponseObject(true);
        } catch (IllegalArgumentException ex) {
            return Utility.newResponseObject(ex.getMessage());
        }
    }

    @GetMapping("/filetest")
    public ModelAndView filetest() {
        return new ModelAndView("filetest");
    }
}
